<?php
/**
 * XmuSlh, web platform of Student Association Federation of Xiamen University
 * 
 * Rewritting one or some pages of StatusNet. 
 * To get the original version, please visit <http://status.net/>.
 * 
 * StatusNet, the distributed open-source microblogging tool
 * 
 * LICENCE: This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * This HtmlOutputter exactly output the php content to the visitor.
 * Currently eliminates the handlers.
 * 
 * 直接往浏览器输出HTML标记语言的包装类.
 * 
 * @author		ytukie <ytukie@gmail.com>
 * @version		0.35
 * 
 * 0.2)  Adds some HTML elements.
 * 0.21) Adds the 'hidden' method.
 * 0.3)  Adds some Javascript-operator methods.
 * 0.31) Adds the 'charset' property.
 * 0.32) Adds the 'password' HTML element. 
 * 0.33) Adds the 'textarea' HTML element.
 * 0.34) Adds the 'readonly' HTML element.
 * 0.35) Adds the 'datetimepicker' element, related to the jQuery plugin!
 * 0.26) Adds the 'instruction' element.
 * 0.27) Adds the 'inputtips' element.
 */

// XmuSlh only.
if ( !defined('XMUSLH')) { exit(1); }

require_once INSTALLDIR . '/lib/slh_xmloutputter.php';

/**
 * Low-level generator for HTML.
 *
 * Abstracts some of the code necessary for HTML generation. Especially
 * has methods for generating HTML form elements. Note that these have
 * been created kind of haphazardly, not with an eye to making a general
 * HTML-creation class.
 */
class HTMLOutputter extends XMLOutputter
{
	/**
     * Constructor.
     *
     * Just wraps the XMLOutputter constructor.
     *
     * @param string  $output 		URI to output to, default = stdout
     * @param boolean $indent 		whether to indent output, default true
     */

    function __construct($output = 'php://output', 
    					 $indent = 'true')
    {
        parent::__construct($output, $indent);
    }
    
    /**
     * Start an HTML document.
     * 
     * Currently ignores the content negotiation...
     */
    function startHTML($type = null)
    {
    	$type = 'text/html;charset=utf-8';
    	$language = 'zh-CN';
    	
    	header('Content-Type: ' . $type);
    	
    	$this->extraHeader();
    	
    	// Strict type dtd.
    	$this->xw->writeDTD('html',
    						'-//W3C//DTD XHTML 1.0 Strict//EN',
                            'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd');
    	$attrs = array(
            'xmlns' => 'http://www.w3.org/1999/xhtml',
            'xml:lang' => $language,
            'lang' => $language
        );
        
        $this->elementStart('html', $attrs);
    }
    
    /**
     * Ends an HTML document.
     */
    function endHTML()
    {
    	$this->elementEnd('html');
    	$this->endXML();
    }
    
    /**
     * To specify additional HTTP headers for the action.
     */
    function extraHeader()
    {
    	// Needs to be overloaded.
    }
    
    /**
     * Output an p element that doing some instruction.
     */
    function instruction($value,
    					 $cls = 'cls_p_instruction')
    {
    	$this->element('p', $cls, $value);
    }
    
    /**
     * Output input tips.
     */
	function inputtips($value,
    				   $cls = 'cls_p_inputtips')
    {
    	$this->element('p', $cls, $value);
    }
    
    /**
     * Output an HTML hidden element.
     */
    function hidden($id, 
    				$value, 
    				$name = null)
    {
    	$this->element('input', array('name' => ($name) ? $name : $id,
    								  'type' => 'hidden',
    								  'id' => $id,
    								  'value' => $value));
    }
    
    /**
     * Output a HTML text input element.
     * 
     * Despite the name, it is specifically for outputting a text
     * input element, not other <input> elements. It outputs a 
     * cluster of elements, including a <label> and an associated
     * inputtips span.
     */
	function input($id, 
				   $label, 
				   $value = null, 
				   $inputtips = null)
    {
        $this->element('label', array('for' => $id), $label);
        $attrs = array('name' => $id,
                       'type' => 'text',
                       'id' => $id);
        if ($value) {
            $attrs['value'] = $value;
        }
        
        $this->element('input', $attrs);
        
        if ($inputtips) {
            $this->inputtips($inputtips);
        }
    }
    
    /**
     * Output a HTML text input with 'readonly' property elemnt.
     */
    function readonly($id,
    				  $label,
    				  $value,
    				  $inputtips = null)
	{
		$this->element('label', array('for' => $id), $label);
        $attrs = array('name' => $id,
                       'type' => 'text',
                       'id' => $id,
                       'value' => $value,
					   'readonly' => 'readonly');
        
        $this->element('input', $attrs);
        
        if ($inputtips) {
             $this->inputtips($inputtips);
        }		  	
	}
    
    /**
     * Output an HTML password input and associated elements.
     */
	function password($id, 
					  $label, 
					  $inputtips = null)
	{
		$this->element('label', array('for' => $id), $label);
		$attrs = array('name' => $id,
					   'type' => 'password',
					   'class' => 'password',
					   'id' => $id);
		$this->element('input', $attrs);
		
		if ($inputtips) {
             $this->inputtips($inputtips);
        }
	}
    
    /**
     * TODO: More css style?
     * 
     * Output a HTML sumbit button.
     */
	function submit($id, 
					$value, 
					$cls = 'submit', 
					$name = null, 
					$title = null)
    {
        $this->element('input', array('type' => 'submit',
                                      'id' => $id,
                                      'name' => ($name) ? $name : $id,
                                      'class' => $cls,
                                      'value' => $value,
                                      'title' => $title));
    }
    
	/**
     * Output an HTML textarea and associated elements
     */
    function textarea($id, 
    				  $label,
    				  $rows = 3,
    				  $cols = 40,
    				  $content = null, 
    				  $inputtips = null)
    {
        $this->element('label', array('for' => $id), $label);
        $this->element('textarea', array('rows' => $rows,
                                         'cols' => $cols,
                                         'name' => $id,
                                         'id' => $id),
                       					 ($content) ? $content : '');
                       
        if ($inputtips) {
             $this->inputtips($inputtips);
        }
    }
    
    /**
     * Output an HTML checkbox and associated elements.
     * 
     * Selected: true, else false.
     */
    function checkbox($id, 
    				  $label,
    				  $checked = false,
    				  $inputtips = null,
    				  $value = 'true',
    				  $disabled = false) 
    {
    	$attrs = array('name' => $id,
    				   'type' => 'checkbox',
    				   'class' => 'checkbox',
    				   'id' => $id);
    	
    	if ($value) {
    		$attrs['value'] = $value;
    	}
    	if ($checked) {
    		$attrs['checked'] = 'checked';
    	}
    	if ($disabled) {
    		$attrs['disabled'] = 'true';
    	}
    	
    	$this->element('input', $attrs);
    	$this->text(' ');
    	$this->element('label', array('for' => $id),
    					$label);
    	
    	if ($inputtips) {
    		 $this->instruction($inputtips);
    	}
    }
    
	/**
     * Output a datetime picker element!
     * 
     * xxxx-xx-xx xx:xx
     */
	function datetimepicker($id,
							$id_date,
							$id_hour,
						    $id_minute, 
						    $label,
						    $inputtips = null)
    {
        $this->element('label', array('for' => $id), $label);

        // Date
        $attrs = array('name' => $id_date,
                       'type' => 'text',
                       'id' => $id_date);
        $this->element('input', $attrs);
        
        // Hour
        $this->elementStart('select', array('id' => $id_hour,
       										'name' => $id_hour,
        									'class' => 'cls_select_time'));
		for ($hour = 0; $hour < 24; ++$hour) {
			$h = sprintf("%02d",$hour);
			$this->element('option', array('value' => $h), $h);
		}
		$this->elementEnd('select');
		
        $this->text(':');
        
        // Minute
       	$this->elementStart('select', array('id' => $id_minute,
        									'name' => $id_minute,
        									'class' => 'cls_select_time'));
		for ($minute = 0; $minute < 60; ++$minute) {
			$m = sprintf("%02d",$minute);
			$this->element('option', array('value' => $m), $m);
		}
		$this->elementEnd('select');
		
        if ($inputtips) {
             $this->inputtips($inputtips);
        }
    }
    
    /**
     * Output a script (almost always javascript) tag.
     */
    function script($src, $type = 'text/javascript')
    {
    	$path = slh_config('javascript', 'path');
    		
    	if (empty($path)) {
    		$path = slh_config('site', 'path') . '/js';
    	}
    		
    	$server = slh_config('site', 'server');
    		
    	if ($path[strlen($path) - 1] != '/') {
    			$path .= '/';
    	}
    		
    	if ($path[0] != '/') {
    		$path = '/' . $path;
    	}
    		
    	// TODO: Fix the version?
    	$src = 'http://' . $server . $path . $src;// . '?version=' . '0.21';
    	
    	$this->element('script', array('type' => $type,
    								   'src' => $src), '');
    }
    
    /**
     * Output a script (almost always javascript) tag with inline
     * code.
     */
    function inlineScript($code, $type = 'text/javascript')
    {
    	$this->elementStart('script', array('type' => $type));
    	
    	if ($type == 'text/javascript') {
    		$this->raw('/*<![CDATA[*/ ');		// XHTML compat.
    		$this->raw($code);
    		$this->raw(' /*]]>*/');				// XHTML compat.
    	} else {
    		$this->raw($code);
    	}
    	
    	$this->elementEnd('script');
    }

	/**
	 * TODO: Need to load the JQuery?
	 * Internal scipt to autofocus the given element on page onload.
	 */
	function autofocus($id)
	{
		$this->inlineScript(
						' $(document).ready(function() {' .
						' var el = $("#' . $id . '");' . 
						' if (el.length) { el.focus(); }' . 
						' });');
	}
	
	/**
     * Output a css link.
     */
    function cssLink($src, 
    				 $theme = null, 
    				 $media = null)
    {
    	$url = parse_url($src);
    	if (empty($url['scheme']) && 
    		empty($url['host']) && 
    		empty($url['query']) && 
    		empty($url['fragment'])) {
    		// TODO: Fix the theme >< and the version?
    		$src = slh_full_path($src);
    		// $src .= '?version=' . '0.21';
    	}
    	
    	$this->element('link', array('rel'	=> 'stylesheet',
    								 'type'	=> 'text/css',
    								 'href'	=> $src,
    								 'media'=> $media));
    }
}
?>